package uk.co.optimisticpanda.dropwizard.dbdeploy;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.reflections.Reflections;
import org.reflections.scanners.ResourcesScanner;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.dbdeploy.exceptions.UnrecognisedFilenameException;
import com.dbdeploy.scripts.ChangeScript;
import com.dbdeploy.scripts.FilenameParser;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Throwables;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.io.InputSupplier;
import com.google.common.io.Resources;
public class ClasspathResourceScanner {
private static final Logger logger = LoggerFactory.getLogger(ClasspathResourceScanner.class);
private final FilenameParser filenameParser = new FilenameParser();
private final Charset encoding;
public ClasspathResourceScanner(Charset encoding) {
this.encoding = encoding;
}
public List<ChangeScript> getChangeScriptsForLocation(String location) {
logger.info("Reading change scripts from location: " + location + "...");
List<ChangeScript> scripts = Lists.newArrayList();
for (String resource : scan(location)) {
try {
String fileName = getFileNameForResource(resource);
long id = filenameParser.extractIdFromFilename(fileName);
scripts.add(new ClasspathChangeScript(id, resource, encoding));
} catch (UnrecognisedFilenameException e) {
// ignore
}
}
return scripts;
}
public static Collection<String> scan(final String path) {
Reflections reflections = new Reflections( //
new ConfigurationBuilder().setScanners( //
new ResourcesScanner()).setUrls( //
ClasspathHelper.forPackage(path)));
Map<String, Multimap<String, String>> store = reflections.getStore().getStoreMap();
Preconditions.checkArgument(store.size() == 1, "Stores should just have one key");
Multimap<String, String> foundResouces = store.values().iterator().next();
return Collections2.filter(foundResouces.values(), new Predicate<String>() {
@Override
public boolean apply(String input) {
return input.startsWith(path);
}
});
}
public static String load(Charset charset, String resourceName) {
URL resource = Resources.getResource(resourceName);
try {
logger.debug("loading resource: {}", resourceName);
return Resources.toString(resource, charset);
} catch (IOException e) {
throw Throwables.propagate(e);
}
}
public static InputSupplier<InputStreamReader> reader(Charset charset, String resourceName) {
URL resource = Resources.getResource(resourceName);
return Resources.newReaderSupplier(resource, charset);
}
public static String getFileNameForResource(String resource) {
URL url = Resources.getResource(resource);
logger.debug("Extracting file name from url: {}", url);
return new File(url.getFile()).getName();
}
}